package com.gitee.beiding.timer;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;

/*
    使用工厂模式创建Timer对象,且一个Factory创建的实例时单例的
 */
public class MyTimerFactory {

    private TaskRepository taskRepository;

    private List<TaskHandler> taskHandlers;

    private MyTimer myTimer;

    public void setTaskRepository(TaskRepository taskRepository) {
        this.taskRepository = taskRepository;
    }

    public void setHandlers(List<TaskHandler> taskHandlers) {
        this.taskHandlers = taskHandlers;
    }

    public MyTimer create() {
        if (myTimer == null) {
            synchronized (this) {
                if (myTimer == null) {
                    if (taskRepository == null) {
                        taskRepository = new TaskRepository() {

                            private Map<String, Task> taskMap = new ConcurrentHashMap<>();

                            private Map<Long, Set<Task>> idMap = new ConcurrentHashMap<>();

                            @Override

                            public void deleteById(String id) {
                                Task task = taskMap.remove(id);
                                if (task != null) {
                                    Set<Task> set = idMap.get(task.getTime());
                                    if (set != null) {
                                        set.remove(task);
                                    }
                                }
                            }

                            @Override
                            public void save(Task task) {

                                String id = UUID.randomUUID().toString();
                                task.setId(id);
                                taskMap.put(id, task);
                                long time = task.getTime();
                                Set<Task> set = idMap.computeIfAbsent(time, k -> Collections.synchronizedSet(new HashSet<Task>()));
                                set.add(task);
                            }

                            @Override
                            public Set<Task> getRange(long startTime, long endTime) {
                                Set<Task> tasks = new HashSet<>();
                                idMap.forEach((t,s)->{
                                    if (t >= startTime && t < endTime) {
                                        tasks.addAll(s);
                                    }
                                });
                                return tasks;
                            }
                        };
                    }

                    if (taskHandlers == null) {
                        taskHandlers = Collections.emptyList();
                    }

                    Dao dao = new Dao(taskRepository);
                    Handlers handlers = new Handlers(taskHandlers);
                    myTimer = new MyTimer(dao, handlers);
                    myTimer.start();
                }
            }
        }
        return myTimer;
    }

}
